package jnpf.zc.controller;
import org.apache.commons.beanutils.BeanUtils;
import cn.hutool.extra.tokenizer.Result;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jnpf.base.ActionResult;
import jnpf.fico.entity.ZcBillEntity;
import jnpf.fico.entity.ZcBillItemEntity;
import jnpf.fico.service.ZcBillItemService;
import jnpf.fico.service.ZcBillService;
import jnpf.htgl.entity.ZcglHtglPabEntity;
import jnpf.htgl.service.ZcglHtglPabService;
import jnpf.permission.service.UserService;
import jnpf.service.AuthService;
import jnpf.zc.entity.AttentionInfo;
import jnpf.zc.service.IAttentionInfoService;
import jnpf.zc.util.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@Api(tags="微信公众号")
@RequestMapping("/tencent/wxAuth")
public class WxLoginController {

    @Autowired
    private IAttentionInfoService attentionInfoService;

    @Value("https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code")
    private String getAccessTokenUrl;
    @Value("https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN")
    private String getUserInfoUrl;
    @Value("wx5e797fa0a396cdc7")
    private String appId;
    @Value("b611acac6c76d0d8ab70be783c9109dd")
    private String secret;
    @Value("http://zc.cqukon.cn/")
    private String baseUrl;

    @Autowired
    private AuthService authService;
    @Autowired
    private UserService userApi;



    @Autowired
    private ZcBillService zcBillService;

    @Autowired
    private ZcBillItemService zcBillItemService;
    @Autowired
    private ZcglHtglPabService zcglHtglPabService;


    /**
     * 根据微信OpenID获取当前应收账单列表（包含主表和子表详情）
     *
     * @param openid   微信用户唯一标识
     * @param pageNo   页码
     * @param pageSize 每页条数
     * @return Result<IPage<Map<String, Object>>> 分页的、包含子表的账单列表
     */
    @ApiOperation(value = "根据微信OpenID获取当前应收账单详情", notes = "流程：openid -> 身份证 -> 合同ID -> 未收款账单(含子表)")
    @GetMapping("/getByOpenidWithItems")
    public ActionResult getCurrentReceivablesByOpenidWithItems(
            @RequestParam String openid,
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {

        if (openid == null || openid.isEmpty()) {
            return ActionResult.fail("参数错误：openid不能为空！");
        }

        // --- 第一步：通过 openid 查询身份证号 ---
        QueryWrapper<ZcglHtglPabEntity> pabQueryWrapper1 = new QueryWrapper<>();
        pabQueryWrapper1.eq("F_CreatorUserId", openid);
        ZcglHtglPabEntity pabInfo = zcglHtglPabService.getOne(pabQueryWrapper1);


        String idCard = pabInfo.getPabIdNo();

        // --- 第二步：通过身份证号查询所有关联的合同ID ---
        QueryWrapper<ZcglHtglPabEntity> pabQueryWrapper2 = new QueryWrapper<>();
        pabQueryWrapper2.eq("PAB_ID_NO", idCard);
        List<ZcglHtglPabEntity> pabList = zcglHtglPabService.list(pabQueryWrapper2);


        List<String> contractIds = pabList.stream()
                .map(ZcglHtglPabEntity::getParentid)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());


        // --- 第三步：根据合同ID列表查询未收款主表账单 ---
        QueryWrapper<ZcBillEntity> billQueryWrapper = new QueryWrapper<>();
        billQueryWrapper.in("CONTRACT_ID", contractIds);
        billQueryWrapper.eq("RECEIPT_STATUS", 0); // 0: 未收款

        Page<ZcBillEntity> page = new Page<>(pageNo, pageSize);
        IPage<ZcBillEntity> billPage = zcBillService.page(page, billQueryWrapper);

        List<ZcBillEntity> billRecords = billPage.getRecords();


        // --- 第四步：查询所有相关的子表数据 ---
        List<String> billIds = billRecords.stream().map(ZcBillEntity::getId).collect(Collectors.toList());
        QueryWrapper<ZcBillItemEntity> itemQueryWrapper = new QueryWrapper<>();
        itemQueryWrapper.in("F_ParentId", billIds);
        List<ZcBillItemEntity> allBillItems = zcBillItemService.list(itemQueryWrapper);

        // --- 第五步：组装主表和子表数据为Map结构 ---
        // 创建一个Map，用于快速查找每个主表对应的子表列表
        Map<String, List<ZcBillItemEntity>> billItemMap = allBillItems.stream()
                .collect(Collectors.groupingBy(ZcBillItemEntity::getParentid));
// --- 将整个 stream().map() 逻辑替换为以下代码 ---

// 遍历主表，为每个主表对象创建一个Map，并将其子表也转为Map列表放入
        List<Map<String, Object>> resultList = billRecords.stream().map(bill -> {
            // 1. 手动创建主表 Map
            Map<String, Object> billMap = new HashMap<>();
            billMap.put("id", bill.getId());
            billMap.put("contractId", bill.getContractId());
            billMap.put("customerId", bill.getCustomerId());
            billMap.put("billNo", bill.getBillNo());
            billMap.put("billAmount", bill.getBillAmount());
            billMap.put("customerName", bill.getCustomerName());
            billMap.put("contractNo", bill.getContractNo());
            billMap.put("leaseSpace", bill.getLeaseSpace());
            billMap.put("project", bill.getProject());
            billMap.put("expenseStartDate", bill.getExpenseStartDate());
            billMap.put("expenseEndDate", bill.getExpenseEndDate());
            billMap.put("planReceiptDate", bill.getPlanReceiptDate());
            billMap.put("receiptStatus", bill.getReceiptStatus());
            // ... 可以根据需要添加更多主表字段

            // 2. 获取当前主表对应的子表列表
            List<ZcBillItemEntity> items = billItemMap.getOrDefault(bill.getId(), Collections.emptyList());

            // 3. 手动创建并填充子表 Map 列表
            List<Map<String, Object>> itemMapList = new ArrayList<>();
            for (ZcBillItemEntity item : items) {
                Map<String, Object> itemMap = new HashMap<>();
                itemMap.put("fId", item.getId());
                itemMap.put("fParentId", item.getParentid());
                itemMap.put("expenseItem", item.getExpenseItem());
                itemMap.put("cycleType", item.getCycleType());
                itemMap.put("cyclePrice", item.getCyclePrice());
                itemMap.put("receiveAmount", item.getReceiveAmount());
                itemMap.put("pendAmount", item.getPendAmount());
                itemMap.put("status", item.getStatus());
                // ... 可以根据需要添加更多子表字段

                itemMapList.add(itemMap);
            }

            // 4. 将子表Map列表放入主表Map中
            billMap.put("billItems", itemMapList);

            return billMap;
        }).collect(Collectors.toList());

// --- 替换结束 ---

        // --- 第六步：构造最终的分页结果并返回 ---
        IPage<Map<String, Object>> resultPage = new Page<>();
        resultPage.setRecords(resultList);
        resultPage.setTotal(billPage.getTotal());
        resultPage.setSize(billPage.getSize());
        resultPage.setCurrent(billPage.getCurrent());
        resultPage.setPages(billPage.getPages());

        return ActionResult.success(resultPage);
    }


    /**
     *
     * @param code
     * @return
     * @throws IOException
     */
    @ApiOperation(value="获取openID", notes="获取openID")
    @PostMapping("/getOpenId")
//    @RequestMapping("/callBack")
    public ActionResult getOpenId(@RequestParam(name="code",required=true) String code) throws IOException {

        //获取access_token
        String url = getAccessTokenUrl.replace("APPID", appId).replace("SECRET", secret).replace("CODE", code);

        String result = HttpClientUtil.doGet(url);
        log.info("获取openID result:" + result);
        //返回结果的json对象
        JSONObject resultObject = JSON.parseObject(result);
        String opendId =  resultObject.getString("openid");

        if (StringUtils.isNotBlank(opendId)){
            LambdaQueryWrapper<AttentionInfo> queryWrapper = new LambdaQueryWrapper<AttentionInfo>();
            queryWrapper.eq(AttentionInfo :: getOpenid, opendId);
//            queryWrapper.last("");
            AttentionInfo attentionInfo = attentionInfoService.getOne(queryWrapper);
            if (attentionInfo == null){
                attentionInfo = new AttentionInfo();
                attentionInfo.setOpenid(opendId);
                attentionInfoService.save(attentionInfo);
            }

            if (StringUtils.isBlank(attentionInfo.getNickname())){

                try {
                    String infoUrl = getUserInfoUrl.replace("ACCESS_TOKEN", resultObject.getString("access_token")).replace("OPENID", opendId);
                    String infoResult = HttpClientUtil.doGet(infoUrl);
                    log.info("获取USER_INFO result:" + infoResult);
                    JSONObject infoResultObject = JSON.parseObject(infoResult);
                    attentionInfo.setNickname(infoResultObject.getString("nickname"));
                    attentionInfo.setSex(infoResultObject.getInteger("sex"));
                    attentionInfo.setProvince(infoResultObject.getString("province"));
                    attentionInfo.setCity(infoResultObject.getString("city"));
                    attentionInfo.setCountry(infoResultObject.getString("country"));
                    attentionInfo.setHeadimgurl(infoResultObject.getString("headimgurl"));
                    attentionInfo.setPrivilege(infoResultObject.getString("privilege"));
                    attentionInfo.setUnionid(infoResultObject.getString("unionid"));
                    attentionInfoService.updateById(attentionInfo);
                } catch (Exception e) {
//                e.printStackTrace();
                }
            }

            Map<String, Object> map = new HashMap<>();
            map.put("opendId", opendId);
            return ActionResult.success(map);
        } else {
            return ActionResult.fail(null);
        }

    }



}
